package model

import (
	ryrpc "admin/rpc"
	"common/helper"
	"database/sql"
	"errors"
	"fmt"
	g "github.com/doug-martin/goqu/v9"
	"github.com/valyala/fasthttp"
	"strconv"
	"time"
)

type MemberBankcard struct {
	Id         string `json:"id" db:"id" cbor:"id"`
	Uid        string `json:"uid" db:"uid" cbor:"uid"`
	Username   string `json:"username" db:"username" cbor:"username"`
	CreatedAt  int    `json:"created_at" db:"created_at" cbor:"created_at"`
	State      int    `json:"state" db:"state" cbor:"state"` //1=正常,2=停用,3=黑名单'
	PixId      string `json:"pix_id" db:"pix_id" cbor:"pix_id"`
	Flag       int    `json:"flag" db:"flag" cbor:"flag"` //1 CPF 2 PHONE 3 EMAIL
	BankName   string `json:"bankname" db:"bankname" cbor:"bankname"`
	BankCode   string `json:"bankcode" db:"bankcode" cbor:"bankcode"`
	PixAccount string `json:"pix_account" db:"pix_account" cbor:"pix_account"`
	RealName   string `json:"real_name" db:"real_name" cbor:"real_name"`
}

type MemberBankData struct {
	T int              `cbor:"t" json:"total"`
	D []MemberBankcard `cbor:"d" json:"d"`
}

type BankCardParam struct {
	PixId    string `json:"pix_id"`
	Flag     string `json:"flag"`
	Uid      string `json:"uid"`
	Page     int    `json:"page"`
	PageSize int    `json:"page_size"`
	OderBY   string `json:"order_by"`
	OderType string `json:"order_type"`
}

func BankCardList(param BankCardParam, ctx *fasthttp.RequestCtx) (MemberBankData, error) {

	data := MemberBankData{}

	where := "1=1"
	oderBy := "a.created_at"
	oderType := "desc"

	if param.Uid != "" {
		where += " and a.uid=" + param.Uid
	}
	if param.PixId != "" {
		where += " and a.pix_id like '%" + param.PixId + "%'"
	}
	if param.Flag != "" {
		where += " and a.flag=" + param.Flag
	}
	loginUser := GetLoginUser(ctx)
	if loginUser.Operator != "" {
		where += " and b.operator_id=" + loginUser.Operator
	} else if loginUser.Businsess != "" {
		where += " and b.business_id=" + loginUser.Businsess
	}

	if param.OderBY != "" {
		oderBy = param.OderBY
	}
	if param.OderType != "" {
		oderType = param.OderType
	}

	table := "tbl_member_bankcard"
	order := oderBy + " " + oderType
	join := " left join tbl_member_base as b on b.uid=a.uid" //玩家表

	offset := (param.Page - 1) * param.PageSize
	if param.Page >= 1 {
		count := "select count(1) from " + table + " as a " + join + " where " + where

		err := meta.MerchantDB.Get(&data.T, count)
		if err != nil {

			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), count), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}
	field := "a.*"

	query := "select " + field + " from " + table + " as a " + join + " where " + where + " order by " + order + " limit " + strconv.Itoa(param.PageSize) + " offset " + strconv.Itoa(offset)

	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	return data, nil
}

func UpdateBankcard(param MemberBankcard, isDelete int8) error {
	table := "tbl_member_bankcard"
	query := ""
	card := MemberBankcard{}
	if param.Id != "" {
		if isDelete == 0 {
			query, _, _ = dialect.Update(table).Set(param).Where(g.Ex{"id": param.Id}).ToSQL()
		} else {
			query, _, _ = dialect.From(table).Select("*").Where(g.Ex{"id": param.Id}).ToSQL()
			meta.MerchantDB.Get(&card, query)
			query, _, _ = dialect.Delete(table).Where(g.Ex{"id": param.Id}).ToSQL()
		}
	} else {
		query, _, _ = dialect.Insert(table).Rows(param).ToSQL()
	}
	_, err := meta.MerchantDB.Exec(query)
	if err != nil {
		return errors.New("数据库错误")
	}

	if isDelete == 1 && card.State == 1 {
		newId := 0
		query, _, _ = dialect.From(table).Select("id").Where(g.Ex{"uid": card.Uid}).ToSQL()
		meta.MerchantDB.Get(&newId, query)
		if newId > 0 {
			query, _, _ = dialect.Update(table).Set(g.Ex{"state": 1}).Where(g.Ex{"id": newId}).ToSQL()
			_, err = meta.MerchantDB.Exec(query)
		}
	}
	return nil
}

type TblBanktype struct {
	Id       int    `json:"id" db:"id" cbor:"id"`
	BankName string `json:"bankname" db:"bankname" cbor:"bankname"`
	BankCode string `json:"bankcode" db:"bankcode" cbor:"bankcode"`
	State    int    `json:"state" db:"state" cbor:"state"`
}

type BankTypeData struct {
	T int           `cbor:"t" json:"total"`
	D []TblBanktype `cbor:"d" json:"d"`
}

type InsertMerchantBankParam struct {
	PixId      string `json:"pix_id"`
	Username   string `json:"username"`
	BankCode   string `json:"bankcode"`
	OperatorId string `json:"operator_id"`
}

type InsertBusinessBankParam struct {
	PixId      string `json:"pix_id"`
	Username   string `json:"username"`
	BankCode   string `json:"bankcode"`
	BusinessId string `json:"business_id"`
}

func MemberCardList(page, pageSize uint, uid, username string) (MemberBankData, error) {

	ex := g.Ex{}
	if uid != "" {
		ex["uid"] = uid
	}
	if username != "" {
		ex["username"] = username
	}
	data := MemberBankData{}
	t := dialect.From("tbl_member_bankcard")
	if page >= 1 {
		query, _, _ := t.Select(g.COUNT(1)).Where(ex).ToSQL()
		err := meta.MerchantDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}

	offset := (page - 1) * pageSize
	query, _, _ := t.Select(colsMemberBankcard...).Where(ex).Offset(offset).Limit(pageSize).Order(g.C("created_at").Desc()).ToSQL()

	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	return data, nil
}

func BankTypeList(page, pageSize uint) (BankTypeData, error) {

	var (
		data BankTypeData
	)
	t := dialect.From("tbl_banktype")
	if page >= 1 {
		query, _, _ := t.Select(g.COUNT(1)).ToSQL()

		err := meta.MerchantDB.Get(&data.T, query)
		if err != nil {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}

		if data.T == 0 {
			return data, nil
		}
	}

	offset := (page - 1) * pageSize
	query, _, _ := dialect.From("tbl_banktype").Select(colsBankType...).Offset(offset).Limit(pageSize).Order(g.C("id").Asc()).ToSQL()

	err := meta.MerchantDB.Select(&data.D, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	return data, nil
}

func BankcardInsert(username string, pixId, bankCode string) error {

	mb, err := MemberFindByUsername(username)
	if err != nil {
		return errors.New(helper.UsernameErr)
	}
	// 判断会员银行卡数目

	// 会员银行卡插入加锁
	lKey := fmt.Sprintf("bc:%s", username)
	err = Lock(lKey)
	if err != nil {
		return err
	}

	bankType, err := bankNameByCode(bankCode)
	if err != nil {
		return errors.New(helper.BankNameOrCodeErr)
	}
	defer Unlock(lKey)

	//开启事务
	tx, err := meta.MerchantDB.Begin()
	if err != nil {
		return pushLog(err, "数据库错误")
	}
	bankcardRecord := g.Record{
		"id":         helper.GenId(),
		"uid":        mb.Uid,
		"username":   username,
		"pix_id":     pixId,
		"created_at": time.Now().Unix(),
		"bankcode":   bankCode,
		"bankname":   bankType.BankName,
	}
	// 更新会员银行卡信息
	query, _, _ := dialect.Insert("tbl_member_bankcard").Rows(bankcardRecord).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		_ = tx.Rollback()

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	memberEx := g.Ex{
		"uid": mb.Uid,
	}
	memberRecord := g.Record{
		"bankcard_total": g.L("bankcard_total+1"),
	}

	// 更新会员信息
	query, _, _ = dialect.Update("tbl_member_base").Set(memberRecord).Where(memberEx).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		_ = tx.Rollback()

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	tx.Commit()

	key := "merchant:bankcard_exist"
	_ = meta.MerchantRedis.SAdd(ctx, key, pixId).Err()
	return nil
}

func bankNameByCode(bankcode string) (TblBanktype, error) {

	var (
		data TblBanktype
	)

	query, _, _ := dialect.From("tbl_banktype").Select(colsBankType...).Where(g.Ex{"bankcode": bankcode}).Limit(1).ToSQL()

	err := meta.MerchantDB.Get(&data, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if err == sql.ErrNoRows {
		return data, errors.New(helper.RecordNotExistErr)
	}

	return data, nil
}

func InsertBankType(bankcode, bankname string) error {

	_, err := bankNameByCode(bankcode)
	if err == nil {
		return errors.New(helper.BankCardExistErr)
	}

	record := g.Record{
		"id":       helper.GenId(),
		"bankcode": bankcode,
		"bankname": bankname,
	}

	// 更新会员信息
	query, _, _ := dialect.Insert("tbl_banktype").Rows(record).ToSQL()
	_, err = meta.MerchantDB.Exec(query)
	if err != nil {

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}
	return nil
}

func MerchantBankcardInsert(parm InsertMerchantBankParam) error {

	mb, err := MemberFindByUnameAndOpeId(parm.Username, parm.OperatorId)
	if err != nil {
		return errors.New(helper.UsernameErr)
	}

	// 会员银行卡插入加锁
	lKey := fmt.Sprintf("bc:%s", parm.Username)
	err = Lock(lKey)
	if err != nil {
		return err
	}

	bankType, err := bankNameByCode(parm.BankCode)
	if err != nil {
		return errors.New(helper.BankNameOrCodeErr)
	}
	defer Unlock(lKey)

	//开启事务
	tx, err := meta.MerchantDB.Begin()
	if err != nil {
		return pushLog(err, "数据库错误")
	}
	bankcardRecord := g.Record{
		"id":         helper.GenId(),
		"uid":        mb.Uid,
		"username":   parm.Username,
		"pix_id":     parm.PixId,
		"created_at": time.Now().Unix(),
		"bankcode":   parm.BankCode,
		"bankname":   bankType.BankName,
	}
	// 更新会员银行卡信息
	query, _, _ := dialect.Insert("tbl_member_bankcard").Rows(bankcardRecord).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		_ = tx.Rollback()

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	memberEx := g.Ex{
		"uid": mb.Uid,
	}
	memberRecord := g.Record{
		"bankcard_total": g.L("bankcard_total+1"),
	}

	// 更新会员信息
	query, _, _ = dialect.Update("tbl_member_base").Set(memberRecord).Where(memberEx).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		_ = tx.Rollback()

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	tx.Commit()

	key := "merchant:bankcard_exist"
	_ = meta.MerchantRedis.SAdd(ctx, key, parm.PixId).Err()
	return nil
}

func MerchantMemberCardList(page, pageSize uint, operatorId, username string) (MemberBankData, error) {

	ex := g.Ex{}
	if operatorId != "" {
		ex["operator_id"] = operatorId
	}
	data := MemberBankData{}
	var d []ryrpc.TblMemberBase
	query, _, _ := dialect.From("tbl_member_base").Select(colsMember...).Where(ex).ToSQL()

	err := meta.MerchantDB.Select(&d, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if len(d) == 0 {
		return data, nil
	}
	newEx := g.Ex{}
	for _, v := range d {
		newEx["uid"] = v.Uid
		if username != "" {
			newEx["username"] = username
		}
		t := dialect.From("tbl_member_bankcard")
		if page >= 1 {
			query, _, _ = t.Select(g.COUNT(1)).Where(newEx).ToSQL()

			err = meta.MerchantDB.Get(&data.T, query)
			if err != nil {
				return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
			}

			if data.T == 0 {
				return data, nil
			}
		}

		offset := (page - 1) * pageSize
		query, _, _ = t.Select(colsMemberBankcard...).Where(newEx).Offset(offset).Limit(pageSize).Order(g.C("created_at").Desc()).ToSQL()

		err = meta.MerchantDB.Select(&data.D, query)
		if err != nil && err != sql.ErrNoRows {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}
	}

	return data, nil
}

func BusinessMemberCardList(page, pageSize uint, businessId, username string) (MemberBankData, error) {

	ex := g.Ex{}
	if businessId != "" {
		ex["business_id"] = businessId
	}
	data := MemberBankData{}
	var d []ryrpc.TblMemberBase
	query, _, _ := dialect.From("tbl_member_base").Select(colsMember...).Where(ex).ToSQL()

	err := meta.MerchantDB.Select(&d, query)
	if err != nil && err != sql.ErrNoRows {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	if len(d) == 0 {
		return data, nil
	}
	newEx := g.Ex{}
	for _, v := range d {
		newEx["uid"] = v.Uid
		if username != "" {
			newEx["username"] = username
		}
		t := dialect.From("tbl_member_bankcard")
		if page >= 1 {
			query, _, _ = t.Select(g.COUNT(1)).Where(newEx).ToSQL()

			err = meta.MerchantDB.Get(&data.T, query)
			if err != nil {
				return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
			}

			if data.T == 0 {
				return data, nil
			}
		}

		offset := (page - 1) * pageSize
		query, _, _ = t.Select(colsMemberBankcard...).Where(newEx).Offset(offset).Limit(pageSize).Order(g.C("created_at").Desc()).ToSQL()

		err = meta.MerchantDB.Select(&data.D, query)
		if err != nil && err != sql.ErrNoRows {
			return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
		}
	}

	return data, nil
}

func BusinessBankcardInsert(param InsertBusinessBankParam) error {

	mb, err := MemberFindByUnameAndProId(param.Username, param.BusinessId)
	if err != nil {
		return errors.New(helper.UsernameErr)
	}

	// 会员银行卡插入加锁
	lKey := fmt.Sprintf("bc:%s", param.Username)
	err = Lock(lKey)
	if err != nil {
		return err
	}

	bankType, err := bankNameByCode(param.BankCode)
	if err != nil {
		return errors.New(helper.BankNameOrCodeErr)
	}
	defer Unlock(lKey)

	//开启事务
	tx, err := meta.MerchantDB.Begin()
	if err != nil {
		return pushLog(err, "数据库错误")
	}
	bankcardRecord := g.Record{
		"id":         helper.GenId(),
		"uid":        mb.Uid,
		"username":   param.Username,
		"pix_id":     param.PixId,
		"created_at": time.Now().Unix(),
		"bankcode":   param.BankCode,
		"bankname":   bankType.BankName,
	}
	// 更新会员银行卡信息
	query, _, _ := dialect.Insert("tbl_member_bankcard").Rows(bankcardRecord).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		_ = tx.Rollback()

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	memberEx := g.Ex{
		"uid": mb.Uid,
	}
	memberRecord := g.Record{
		"bankcard_total": g.L("bankcard_total+1"),
	}

	// 更新会员信息
	query, _, _ = dialect.Update("tbl_member_base").Set(memberRecord).Where(memberEx).ToSQL()
	_, err = tx.Exec(query)
	if err != nil {
		_ = tx.Rollback()

		return pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	tx.Commit()

	key := "merchant:bankcard_exist"
	_ = meta.MerchantRedis.SAdd(ctx, key, param.PixId).Err()
	return nil
}

func BankcardFindOne(id string) (MemberBankcard, error) {

	var (
		data MemberBankcard
	)

	query, _, _ := dialect.From("tbl_member_bankcard").Select(colsMemberBankcard...).Where(g.Ex{"id": id}).Limit(1).ToSQL()
	//
	err := meta.MerchantDB.Get(&data, query)
	if err != nil {
		return data, pushLog(fmt.Errorf("%s,[%s]", err.Error(), query), "数据库错误")
	}

	return data, nil
}
